import path from 'path';
import fs from 'fs';
import { getDistPath } from '../../utils/file.util';
import { BASE_DIST, BASE_FROM } from '../../constant';

const cheerio = require('cheerio');

const INIT_GLOBAL_DATA = {
  DIST: BASE_DIST,
  FROM: BASE_FROM,
  REWRITE_A_SUFFIX_FUN: (originLink: string): string => {
    let suffix = '';
    if (!originLink.trimEnd().endsWith('.html') || !originLink.trimEnd().endsWith('.htm')) {
      suffix = '/index.html';
    }
    return suffix;
  },
  CUSTOM_SEPARATOR: '/'
};

let DIST = INIT_GLOBAL_DATA.DIST;
let FROM = INIT_GLOBAL_DATA.FROM;
let REWRITE_A_SUFFIX_FUN = INIT_GLOBAL_DATA.REWRITE_A_SUFFIX_FUN;
let CUSTOM_SEPARATOR = INIT_GLOBAL_DATA.CUSTOM_SEPARATOR;


async function replaceHtmlLink(filePath: string) {
  const html = await fs.promises.readFile(filePath);
  const $ = cheerio.load(html);
  const targetSelector = [
    ['link', 'href'],
    ['script', 'src'],
    ['img', 'src'],
  ];
  targetSelector.forEach(([sel, sym]) => {
    $(sel).map((i, ele) => {
      const originLink = ele.attribs[sym];
      if (originLink && originLink.startsWith('/')) {
        $(ele).attr(
          sym,
          path.relative(
            path.dirname(filePath),
            path.join(FROM, originLink).split(path.sep).join(CUSTOM_SEPARATOR)
          ).split(path.sep).join(CUSTOM_SEPARATOR)
        );
      }
    });
  });

  $('a').map((i, ele) => {
    const originLink = ele.attribs['href'];
    if (originLink && originLink.startsWith('/')) {
      $(ele).attr(
        'href',
        path.relative(
          path.dirname(filePath),
          path.join(FROM, originLink).split(path.sep).join(CUSTOM_SEPARATOR)
        ).split(path.sep).join(CUSTOM_SEPARATOR) + REWRITE_A_SUFFIX_FUN(originLink)
      );
    }
  });

  return fs.promises.writeFile(getDistPath(filePath, FROM, DIST), $.html());
}

async function dealFile(filePath: string) {
  if (filePath.endsWith('.html') || filePath.endsWith('.htm')) {
    return replaceHtmlLink(filePath);
  } else {
    return fs.promises.copyFile(filePath, getDistPath(filePath, FROM, DIST));
  }
}


async function recursionFiles(from: string) {
  const files = await fs.promises.readdir(from, { withFileTypes: true });
  const fileInfoPromise = files.map(fileInfo => {
    const targetFile = path.join(from, fileInfo.name);
    if (fileInfo.isFile()) {
      return dealFile(targetFile);
    } else {
      const dirPath = getDistPath(targetFile, FROM, DIST);
      if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath);
      }
      return recursionFiles(targetFile);
    }
  });
  return Promise.all(fileInfoPromise);
}

export function main(from?: string, dist?: string, options: {
  rewriteASuffix?: (src: string) => string; // 重写a标签链接的后缀名
  customSeparator?: string; // 分隔符
} = {}) {
  if (from) {
    FROM = from;
  }
  if (dist) {
    DIST = dist;
  }
  if (options.rewriteASuffix) {
    REWRITE_A_SUFFIX_FUN = options.rewriteASuffix;
  }
  if (options.customSeparator) {
    CUSTOM_SEPARATOR = options.customSeparator;
  }
  fs.mkdirSync(DIST);
  return recursionFiles(FROM).finally(() => {
    DIST = INIT_GLOBAL_DATA.DIST;
    FROM = INIT_GLOBAL_DATA.FROM;
    REWRITE_A_SUFFIX_FUN = INIT_GLOBAL_DATA.REWRITE_A_SUFFIX_FUN;
  });
}
